trait Button {
    fn press(&self);
}
trait CheckBox {
    fn switch(&self);
}

trait GuiFactory {
    type B: Button;
    type C: CheckBox;
    fn create_button(&self ) -> Self::B;
    fn create_checkbox(&self) -> Self::C;
}







#[derive(Debug)]
struct WinButton {
    name: String, 
}

impl Button for WinButton {
    fn press(&self) {
        println!("WinButton:{:?}", &self.name)
    }
}

#[derive(Debug)]
struct WinCheckBox {
    name : String ,
}
impl CheckBox for WinCheckBox {
    fn switch(&self) {
        println!("WinCheckBox:{:?}", &self.name)
    }
}


struct WinGuiFactory {
}

impl GuiFactory for WinGuiFactory {
    type B = WinButton;
    type C = WinCheckBox;
    fn create_button(&self) -> Self::B {
        WinButton{ name: "win-btn-1".to_owned()}
    }
    fn create_checkbox(&self) -> Self::C {
        WinCheckBox {name: "win-cb-1".to_owned()}
    }
}

#[derive(Debug)]
struct LinuxButton {
    name: String, 
}

impl Button for LinuxButton {
    fn press(&self) {
        println!("LinuxButton:{:?}", &self.name)
    }
}

#[derive(Debug)]
struct LinuxCheckBox {
    name : String ,
}
impl CheckBox for LinuxCheckBox {
    fn switch(&self) {
        println!("LinuxCheckBox:{:?}", &self.name)
    }
}


struct LinuxGuiFactory {
}

impl GuiFactory for LinuxGuiFactory {
    type B = LinuxButton;
    type C = LinuxCheckBox;
    fn create_button(&self) -> Self::B {
        LinuxButton{ name: "linux-btn-1".to_owned()}
    }
    fn create_checkbox(&self) -> Self::C {
        LinuxCheckBox {name: "linux-cb-1".to_owned()}
    }
}



fn render(gui_factory: impl GuiFactory) {
    gui_factory.create_button().press();
    gui_factory.create_checkbox().switch();
}




#[cfg(test)]
mod test {
    use super::*;
    #[test]
    fn test(){
        render(WinGuiFactory{});
        render(LinuxGuiFactory{});
    }
}



